//任意数阶乘
function factorial(n) {
    if (n <= 0) {
        return 1;
    }
    return n * factorial(n - 1);
}



//时间差
function leadTime(time1, time2, callback) {
    let differ = parseInt(Math.abs(time1.getTime() - time2.getTime()) / 1000);
    let day = parseInt(differ / (60 * 60 * 24));
    let hours = parseInt(differ % (60 * 60 * 24) / (60 * 60));
    let minutes = parseInt(differ % (60 * 60) / 60);
    let seconds = parseInt(differ % 60);
    let obj = {};
    obj.day = day;
    obj.hours = hours;
    obj.minutes = minutes;
    obj.seconds = seconds;
    callback(obj);
}



//两个数字间的随机数,包小也包大;
function randomNum(n1, n2) {
    let maxNum = Math.max(n1, n2);
    let minNum = Math.min(n1, n2);
    return parseInt(Math.random() * (maxNum - minNum + 1) + minNum);
}



//cookie增、改
//语法：document.cookie = name=value[;expires=date][;path=路径][;domain=域名]
function setCookie(key, value, options) {
    options = options || {};
    if (typeof options.expires == "number") {
        var date = new Date();
        date.setDate(date.getDate() + options.expires);
    }
    return document.cookie = [
        key + "=" + value,
        typeof options.expires == "number" ? ";expires=" + date : "",
        typeof options.path == "string" ? ";path=" + options.path : "",
        typeof options.domain == "string" ? ";domain" + options.domain : ""
    ].join("");
}



//cookie查(获取)
function getCookie(key) {
    let cookieArr = document.cookie.split('; ');
    for (let i = 0; i < cookieArr.length; i++) {
        let cookieItem = cookieArr[i].split('=');
        if (key == cookieItem[0]) {
            return cookieItem[1];
        }
    }
    return '';
}



//cookie删掉某个cookie值
function removeCookie(key) {
    setCookie(key, "", { expires: -1 });
}


// 多属性运动函数减速运动
function move(ele, target, fn = () => { }) {
    let timerObj = {};
    for (let key in target) {
        timerObj[key] = setInterval(function () {

            let current;
            let distance;
            if (key == 'opacity') {
                current = window.getComputedStyle(ele)[key] * 100;
                distance = (target[key] * 100 - current) / 10;
                distance = distance > 0 ? Math.ceil(distance) : Math.floor(distance);
                current = current / 100;
                distance = distance / 100;
            } else {
                current = parseInt(window.getComputedStyle(ele)[key]);
                distance = (target[key] - current) / 10;
                distance = distance > 0 ? Math.ceil(distance) : Math.floor(distance);
            }

            if (current == target[key]) {
                clearInterval(timerObj[key]);
                delete timerObj[key];
                let n = 0;
                for (let i in timerObj) n++;
                if (n === 0) fn();
            } else if ('opacity' == key) {
                ele.style[key] = distance + current;
            } else {
                ele.style[key] = distance + current + 'px';
            }
        }, 20)
    }
}


// 封装一个时间格式化的函数(补零操作),返回一个对象;
function dates(date) {
    let year = date.getFullYear();
    let month = date.getMonth() + 1;
    let dates = date.getDate();
    let hour = date.getHours();
    let minute = date.getMinutes();
    let second = date.getSeconds();
    let day = date.getDay();

    month = month <= 10 ? '0' + month : month;
    dates = dates <= 10 ? '0' + dates : dates;
    hour = hour <= 10 ? '0' + hour : hour;
    minute = minute <= 10 ? '0' + minute : minute;
    second = second <= 10 ? '0' + second : second;

    let obj = {};
    let dayArr = ['星期天', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];

    obj.month = month;
    obj.dates = dates;
    obj.hour = hour;
    obj.minute = minute;
    obj.second = second;
    obj.week = dayArr[day];
    return obj;
}

//url参数字符串转对象;如:id=1&name=zhangsan&age=18&className=2003 => {id: "1", name: "zhangsan", age: "18", className: "2003"}
function strToObj(dataStr) {
    let arr = dataStr.split('&');
    let obj = {};
    for (let i = 0; i < arr.length; i++) {
        let newArr = arr[i].split('=');
        obj[newArr[0]] = newArr[1];
    }
    return obj;
}


//把对象转换成url参数数据，也就是带&的参数
function objToStr(obj) {
    let str = '';
    for (let key in obj) {
        str += key + '=' + obj[key] + '&';
    }
    return str.substr(0, str.length - 1);
}


//随机颜色16进制
function ranColor() {
    let arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'a', 'b', 'c', 'd', 'e', 'f'];
    let colorStr = '#';
    for (let i = 0; i < 6; i++) {
        colorStr += arr[parseInt(Math.random() * 16)];
    }
    return colorStr;
}

/**
 * formate: 序列化URL
 * formate([url | string], data | object);
 * 
 * @return
 * 
 * 1. key1=value1&key2=value2;
 * 2. url?key1=value1&key2=value2;
 * 
 * */
function formate(url, data) {
    var method = 'GET';
    if (arguments.length == 1) {
        method = 'POST';
        data = url;
        url = '';
    }
    var start = true;
    for (var key in data) {
        if (method == 'GET') {
            url += (start ? "?" : "&") + key + "=" + data[key];
        } else if (method == 'POST') {
            url += (start ? "" : "&") + key + "=" + data[key];
        }
        start = false;
    }
    return url;
}

/**
* 
* ajax: 发送get、post、jsonp请求
* ajax([method | string], url | string, callback | function, data | object);
* 
* */
function ajax(options) {
    options = Object.assign({
        method: 'GET',
        callback: function () { },
        url: '',
        data: {},
        jsonpcallback: 'callback'
    }, options)

    if (options.method.toUpperCase() == 'JSONP') {
        var script = document.createElement('script');
        script.src = formate(options.url, options.data);
        document.body.appendChild(script);
        window[options.jsonpcallback].onload = function (data) {
            options.callback(data)
        }
    } else {
        var xhr = new XMLHttpRequest();
        xhr.open(options.method, options.method.toUpperCase() == 'GET' ? formate(options.url, options.data) : options.url);
        if (options.method.toUpperCase() == 'POST') {
            xhr.setRequestHeader("content-type", "application/x-www-form-urlencoded");
        }
        xhr.send(options.method.toUpperCase() == 'POST' ? formate(options.data) : null);
        xhr.onreadystatechange = function () {
            if (xhr.readyState == 4 && /^2\d{2}/.test(xhr.status)) {
                options.callback(xhr.responseText);
            }
        }
    }
}